package org.example.servicelisten.websocket;

import com.alibaba.fastjson.JSON;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import org.springframework.stereotype.Component;

import jakarta.websocket.OnClose;
import jakarta.websocket.OnError;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Component
@ServerEndpoint("/ws/{sid}")
public class WebSocketServer {

    private static Map<String, Session> sessionMap = new ConcurrentHashMap<>();

    @OnOpen
    @Operation(summary = "WebSocket连接端点", description = "建立WebSocket连接")
    @Parameter(in = ParameterIn.PATH, name = "sid", description = "学生ID", required = true, schema = @Schema(type = "string"))
    @ApiResponse(responseCode = "101", description = "连接成功")
    public void onOpen(Session session, @PathParam("sid") String sid) {
        System.out.println("WebSocket已连接：" + session.getId() + ", 用户ID: " + sid);
        
        sessionMap.put(sid, session);
        
        // 发送连接成功消息
        sendMessage(session, "连接成功");
    }

    @OnMessage
    @Operation(summary = "接收消息", description = "接收来自客户端的消息")
    @Parameter(in = ParameterIn.PATH, name = "sid", description = "学生ID", required = true, schema = @Schema(type = "string"))
    public void onMessage(String message, @PathParam("sid") String sid) {
        System.out.println("收到消息：" + message + ", 来自用户: " + sid);
        
        // 处理业务消息...
        // 可以在这里处理客户端发送的具体业务消息
    }

    @OnClose
    @Operation(summary = "关闭连接", description = "关闭WebSocket连接")
    @Parameter(in = ParameterIn.PATH, name = "sid", description = "学生ID", required = true, schema = @Schema(type = "string"))
    public void onClose(@PathParam("sid") String sid) {
        System.out.println("WebSocket已关闭：" + sid);
        sessionMap.remove(sid);
    }
    
    @OnError
    public void onError(Session session, Throwable error, @PathParam("sid") String sid) {
        System.err.println("WebSocket发生错误：" + sid + ", 错误: " + error.getMessage());
        sessionMap.remove(sid);
        error.printStackTrace();
    }
    
    /**
     * 安全发送消息
     */
    private void sendMessage(Session session, String message) {
        try {
            if (session != null && session.isOpen()) {
                synchronized (session) {
                    session.getBasicRemote().sendText(message);
                }
            }
        } catch (IOException e) {
            System.err.println("发送消息失败: " + e.getMessage());
        }
    }

    public static void sendToAllClients(String message) {
        for (Map.Entry<String, Session> entry : sessionMap.entrySet()) {
            String sid = entry.getKey();
            Session session = entry.getValue();
            try {
                if (session != null && session.isOpen()) {
                    synchronized (session) {
                        session.getBasicRemote().sendText(message);
                    }
                } else {
                    // 移除无效会话
                    sessionMap.remove(sid);
                }
            } catch (Exception e) {
                System.err.println("发送消息到客户端失败: " + sid + ", 错误: " + e.getMessage());
                // 移除无效会话
                sessionMap.remove(sid);
            }
        }
    }

    public static void sendToStudents(String[] messages, Set<String> sids) {
        String type = messages[0];
        String content = messages[1];
        
        for(String sid : sids) {
            try {
                Session session = sessionMap.get(sid);
                if(session != null && session.isOpen()) {
                    // 构建包含操作类型和内容的消息
                    Map<String, String> messageMap = new HashMap<>();
                    messageMap.put("type", type);
                    messageMap.put("content", content);
                    
                    synchronized (session) {
                        session.getBasicRemote().sendText(JSON.toJSONString(messageMap));
                    }
                } else {
                    // 移除无效会话
                    sessionMap.remove(sid);
                }
            } catch (Exception e) {
                System.err.println("发送消息到学生失败: " + sid + ", 错误: " + e.getMessage());
                sessionMap.remove(sid);
            }
        }
    }
    
    /**
     * 获取在线用户数量
     */
    public static int getOnlineCount() {
        return sessionMap.size();
    }
    
    /**
     * 检查用户是否在线
     */
    public static boolean isUserOnline(String sid) {
        Session session = sessionMap.get(sid);
        return session != null && session.isOpen();
    }
}